home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / comm / wxmodem.zip / WXMOPORT.INC < prev    next >
Text File  |  1986-10-29  |  12KB  |  322 lines

  1. {$U-,C-,I-,K-}
  2. type
  3.     tCport = (com1, com2);
  4.     tSaveInt = record                  {Save interrupt vector address}
  5.        IP :  integer;
  6.        CS :  integer;
  7.     end;
  8.     tRegs    = record                  {Dos registers}
  9.        AX, BX, CX, DX, BP, SI, DI, DS, ES, Flags : integer;
  10.     end;
  11. Const
  12.      RECV_BUF_SIZE = 2048;             {this may be changed to
  13.                                         whatever size you need}
  14. { *** Port addresses *** }
  15.      cRBR: array[com1..com2] of integer = ($3F8,$2F8);
  16.                                        {Receive Buffer Register}
  17.      cTHR: array[com1..com2] of integer = ($3F8,$2F8);
  18.                                        {Transmitter Holding Register: the
  19.                                         serial port address we use to send
  20.                                         data}
  21.      cIER: array[com1..com2] of integer = ($3F9,$2F9);
  22.                                        {Interrupt Enable Register for the
  23.                                         serial port}
  24.      cLCR: array[com1..com2] of integer = ($3FB,$2FB);
  25.                                        {Line Control Register for the serial
  26.                                         port. Determines data bits, stop bits
  27.                                         and parity, contributes to setting
  28.                                         baud-rate}
  29.      cMCR: array[com1..com2] of integer = ($3FC,$2FC);
  30.                                        {Modem Control Register}
  31.      cLSR: array[com1..com2] of integer = ($3FD,$2FD);
  32.                                        {Line Status Register}
  33.      cMSR: array[com1..com2] of integer = ($3FE,$2FE);
  34.                                        {Modem Status Register}
  35.      IMR = $021;                       {Interrupt Mask Register port address
  36.                                         of Intel 8259A Programmable Interrupt
  37.                                         controller}
  38. { *** Masks *** }
  39.      ENABLE_OUT2 = 8;                  {Setting bit 3 of MCR enables OUT2}
  40.      ENABLE_DAV = 1;                   {Setting bit 0 of IER enables Data
  41.                                         AVailable interrupt from serial port}
  42.      ENABLE_IRQ: array[com1..com2] of integer = ($00EF,$00F7);
  43.                                        {Clearing bit of IMR enables serial
  44.                                         interrupts to reach the CPU}
  45.      DISABLE_OUT2 = 1;                 {Clearing MCR disables OUT2}
  46.      DISABLE_DAV = 0;                  {Clearing IER disables Data
  47.                                        AVailable interrupt from serial port}
  48.      DISABLE_IRQ: array[com1..com2] of integer = ($0010,$0008);
  49.                                        {Setting bit of IMR stops serial
  50.                                         interrupts from reaching the CPU}
  51.      cINVLIST: array[com1..com2] of integer = ($000C,$000B);
  52.                                        {Interrupt vector number}
  53.      SET_BAUD = $80;                   {Setting bit 7 of LCR allows us to set
  54.                                         the baud rate of the serial port}
  55.      SET_PARMS = $7F;                  {Clearing bit 7 of LCR allows us to set
  56.                                         non-baud-rate parameters on the
  57.                                         serial port}
  58. Type
  59.     parity_set        = (none,even);    {readability and expansion}
  60. Var
  61.    SaveInt                           : tSaveInt;
  62.    Regs                              : tRegs;
  63.    RBR, THR, IER, LCR, MCR, LSR, MSR : integer;
  64.    INVLIST                           : integer;
  65.    SavIER, SavLCR, SavMCR, SavIMR    : integer;
  66.    buf_start, buf_end    : integer;    {NOTE: these will change by them-
  67.                                         selves in the background}
  68.    recv_buffer           : array [1..RECV_BUF_SIZE] of byte;
  69.                                        {also self-changing}
  70.    speed                 : integer;    {I don't know the top speed these
  71.                                         routines will handle}
  72.    dbits                 : 7..8;       {only ones most people use}
  73.    stop_bits             : 1..2;       {does anyone use 2?}
  74.    parity                : parity_set;  {even and none are the common ones}
  75.    Cport                 : tCport;     {set at initialization}
  76.  
  77. function cgetc(TimeLimit : integer) : integer;
  78. {if a byte is recieved at COM1/COM2: in less than TimeLimit seconds,
  79.  returns byte as an integer, else returns -1}
  80. const
  81.      TIMED_OUT = -1;
  82. begin
  83.      TimeLimit := TimeLimit shl 10;     {convert TimeLimit to millisecs}
  84.      while (buf_start = buf_end) and (TimeLimit > 0) do
  85.      begin
  86.           delay(1);
  87.           TimeLimit := pred(TimeLimit)
  88.      end;
  89.      if (TimeLimit >= 0) and (buf_start <> buf_end) then
  90.      begin
  91.           inline ($FA);            {suspend interrupts}
  92.           cgetc := recv_buffer[buf_start];
  93.           buf_start := succ(buf_start);
  94.           if buf_start > RECV_BUF_SIZE then
  95.           buf_start := 1;
  96.           inline ($FB);            {resume interrupts}
  97.      end
  98.      else
  99.          cgetc := TIMED_OUT;
  100. end;
  101.  
  102. procedure send(c : byte);
  103. var
  104.    a : byte;
  105. begin
  106. {
  107.   repeat
  108.        a := port[LSR]
  109.   until odd(a shr 5);
  110.   port[THR] := c;
  111.  }
  112.   inline(
  113.      $8B/$16/LSR/   {in: mov dx,[LSR]}
  114.      $EC/               {in  al,dx}
  115.      $24/$20/           {and al,20}
  116.      $74/$F7/           {jz  in}
  117.      $8B/$16/THR/       {mov dx,[THR]}
  118.      $36/               {ss:}
  119.      $8B/$86/c/         {mov ax,[bp+c]}
  120.      $EE                {out dx,al}
  121.         );
  122. end;
  123.  
  124.  
  125. {Communications routines for TURBO Pascal written by Alan Bishop,
  126.  modified slightly by Scott Murphy.  Modified by Peter Boswell to
  127.  add COM2, saving the original interrupt vector, more inline code.
  128.  Handles standart COM1/COM2: ports with interrupt handling.  Includes
  129.  support for only one port, and with no overflow, parity, or other
  130.  such checking.  However, even some of the best communication programs
  131.  don't do this anyway, and I never use it.  If you make modifications,
  132.  please send me a copy if you have a simple way of doing it (CIS EMAIL,
  133.  Usenet, MCI Mail, etc)  Hope these are useful.
  134.  
  135. Alan Bishop - CIS      - 72405,647
  136.               Usenet   - bishop@ecsvax
  137.               MCI Mail - ABISHOP
  138. }
  139. procedure update_uart;
  140. {uses dbits, stop_bits, and parity}
  141. var
  142.    newparm, oldLCR : byte;
  143. begin
  144.  newparm := dbits-5;
  145.  if stop_bits = 2 then newparm := newparm + 4;
  146.  if parity = even then newparm := newparm + 24;
  147.  oldLCR := port[LCR];
  148.  port[LCR] := oldLCR and SET_PARMS;
  149.  port[LCR] := newparm;
  150. end;
  151.  
  152. procedure term_ready(state : boolean);
  153. {if state = TRUE then set RTS true else set false}
  154. var
  155.    OldMCR : byte;
  156. begin
  157.      OldMCR := port[MCR];
  158.      if state then
  159.         port[MCR] := OldMCR or 1
  160.      else
  161.          port[MCR] := OldMCR and $FE
  162. end;
  163.  
  164. function carrier : boolean;
  165. {true if carrier, false if not}
  166. begin
  167.  carrier := odd(port[MSR] shr 7);
  168. end;
  169.  
  170. procedure set_up_recv_buffer;
  171. begin
  172.  buf_start := 1;
  173.  buf_end   := 1;
  174. end;
  175.  
  176. procedure new_baud(rate : integer);
  177. {has no problems with non-standard bauds}
  178. var
  179.    OldLCR : byte;
  180. begin
  181.  if rate <= 9600 then
  182.  begin
  183.   speed := rate;
  184.   rate := trunc(115200.0/rate);
  185.   OldLCR := port[LCR] or SET_BAUD;
  186.   port[LCR] := OldLCR;
  187.   port[THR] := lo(rate);
  188.   port[IER] := hi(rate);
  189.   port[LCR] := OldLCR and SET_PARMS;
  190.  end;
  191. end;
  192.  
  193. procedure init_port;
  194. {installs interrupt sevice routine for serial port}
  195. var a,b : integer;
  196.     buf_len : integer;
  197. begin
  198.  RBR := cRBR[Cport];
  199.  THR := cTHR[Cport];
  200.  IER := cIER[Cport];
  201.  LCR := cLCR[Cport];
  202.  MCR := cMCR[Cport];
  203.  LSR := cLSR[Cport];
  204.  MSR := cMSR[Cport];
  205.  INVLIST := cINVLIST[Cport];
  206.  update_uart;
  207.  new_baud(speed);
  208.  buf_len := RECV_BUF_SIZE;
  209.  
  210.  {save the original vector}
  211.  
  212.  with Regs do begin
  213.    AX := $3500 + INVLIST;
  214.    MsDos(Regs);
  215.    SaveInt.CS := ES;
  216.    SaveInt.IP := BX;
  217.  end;
  218.  
  219.  {this is the background routine}
  220.  
  221.  inline (
  222.               $FA/                     {cli}
  223.               $1E/                     {push ds}
  224.               $0E/                     {push cs}
  225.               $A1/INVLIST/